
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Tama_Chan.AI;
using Tama_Chan.GameEngine_ns;
using Tama_Chan.Utils;


namespace Tama_Chan.Entities_ns
{
   public class Enemy : GameEntity
   {
      public static readonly Color NormalColor = Color.Tomato;
      public static readonly Color FleeingColor = new Color(255, 180, 150);

      public Enemy(GameEngine gameEngine, Vector2 position)
      {
         GameEngine = gameEngine;
         Texture = GameEngine.CircleTexture;
         Position = position;
         Color = NormalColor;
         Speed = 7;
         TurnSpeed = 2f;
         Velocity = AIUtils.GetRandomVelocity(5, Random);
         Depth = GameEngine.EnemyDepth;
			// ToDo: Zero???
         Origin = new Vector2(0);
         SoundOne = GameEngine.GulpSoundEffect.CreateInstance();
         SoundTwo = GameEngine.HitWallSoundEffect.CreateInstance();
         Target = GameEngine.Player;
         IntervalOne = GeneralUtils.GetSecondsAsTicks(5);
         HealthValue = -20;
      }


      public override void Update(GameTime gameTime)
      {
         AccumulatedTicksOne += gameTime.ElapsedGameTime.Ticks;

         if(GameEngine.PowerPellet.State == PowerPelletState.Attacking && Color == FleeingColor)
         {
            if(AccumulatedTicksOne > IntervalOne)
            {
               AccumulatedTicksOne = AccumulatedTicksOne - IntervalOne;
               Velocity = AIUtils.GetRandomVelocity(Speed, Random);
            }
            Position += Velocity;
         }
         else
         {
            // Roll for update to target for this Enemy.
            if(AccumulatedTicksOne > IntervalOne)
            {
               AccumulatedTicksOne = AccumulatedTicksOne - IntervalOne;

               // Pick new target
               if(Random.Next(100) <= 20)
               {
                  // Get a list of teleporters not being camped by enemies.
                  IList<GameEntity> availableTeleporters =
                     GameEngine.TeleporterList.Where(
                        teleporter => GameEngine.EnemyList.All(enemy => enemy.Target != teleporter)).Cast<GameEntity>().
                        ToList();

                  // Today there are only 4 enemies, so it's impossible for there not to be an open one...
                  Target = availableTeleporters[Random.Next(availableTeleporters.Count)];
               }
               else
               {
                  // Target is the player, there are actually 4 possible targets: the player itself and
                  // the three positions it maintains: nose, right and left. Roll to see if one should be picked.
                  bool bodyIsOpen = true;
                  bool noseIsOpen = true;
                  bool leftIsOpen = true;
                  bool rightIsOpen = true;

                  for(int i = 0; i < GameEngine.EnemyList.Count; i++)
                  {
                     var enemy = GameEngine.EnemyList[i];

                     if(enemy == this)
                     {
                        // Don't take current target into account because it's what we want to get rid of.
                        continue;
                     }

                     // Each enemy could be assigned to a player part OR one of the 4 teleporters.
                     // Teleporters are not taken into account for this assignment.
                     if(enemy.Target == GameEngine.Player)
                     {
                        bodyIsOpen = false;
                     }
                     else if(enemy.Target == GameEngine.Player.Nose)
                     {
                        noseIsOpen = false;
                     }
                     else if(enemy.Target == GameEngine.Player.PerpendicularClockwise)
                     {
                        rightIsOpen = false;
                     }
                     else if(enemy.Target == GameEngine.Player.PerpendicularCounterClockwise)
                     {
                        leftIsOpen = false;
                     }
                  }

                  if(bodyIsOpen)
                  {
                     Target = GameEngine.Player;
                  }
                  else if(rightIsOpen)
                  {
                     Target = GameEngine.Player.PerpendicularClockwise;
                  }
                  else if(leftIsOpen)
                  {
                     Target = GameEngine.Player.PerpendicularCounterClockwise;
                  }
                  else if(noseIsOpen)
                  {
                     Target = GameEngine.Player.Nose;
                  }
               }
            }

            // Update the Enemy position
            if(Target is Teleporter)
            {
               // !- This could be done just once in the entity -!
               // If the target is a Teleporter, the enemy won't be trying to kill it,
               // just sit in the middle, so if already closer than speed just camp it.
               var teleporterCenter =
						new Vector2(Target.Position.X + ((float)Target.Bounds.Width - Bounds.Width) / 2f,
										Target.Position.Y + ((float)Target.Bounds.Height - Bounds.Height) / 2f);
               if(Vector2.Distance(teleporterCenter, Position) < Speed)
               {
                  Position = teleporterCenter;
               }
               else
               {
                  // In the case of Teleporters as targets, don't seek to their Position, but to their center.
                  Velocity += SteeringBehaviors.Seek(this, teleporterCenter);
                  Position += Velocity;
               }
            }
            else
            {
               Velocity += SteeringBehaviors.SeekWithTurnSpeed(this, TurnSpeed, Target);
               Position += Velocity;
            }
         }

         base.Update(gameTime);
      }


      public override void Draw()
      {
			GameEngine.Game1.SpriteBatch.Draw(Texture, Position, null, Color, 0f, Origin, Vector2.One, SpriteEffects.None, Depth);
			GameEngine.Game1.SpriteBatch.Draw(Texture, Position, null, Color, 0f, Origin, Vector2.One, SpriteEffects.None, Depth);
         base.Draw();
      }

   }
}
